local Style = _ENV.import("./Style.lua");
local StyleSheet = commonlib.inherit(nil);

-- -- 获取尾部选择器
-- local function GetTailSelector(comboSelector)
--     if (not comboSelector) then return end

--     comboSelector = string.gsub(comboSelector, "%s*$", "");

--     -- 伪类选择器
--     selector = string.match(comboSelector, ":nth%-child%((%d-)%)$");
--     if (selector) then return selector, "nth-child", string.gsub(comboSelector, ":nth%-child%(%d-%)$", "") end 

--     -- 属性选择器
--     selector = string.match(comboSelector, "%[([%w%d=]-)%]$");
--     if (selector) then return selector, "[", string.gsub(comboSelector, "%[[%w%d=]-%]$", "") end

--     -- 后代选择器 div p
--     local selector = string.match(comboSelector, "%s* ([^%s%+%~%>]-)$");
--     if (selector) then return selector, " ", string.gsub(comboSelector, "%s* [^%s%+%~%>]-$", "") end

--     -- 子选择器 div>p
--     selector = string.match(comboSelector, "%s*%>%s*([^%s%+%~%>]-)$");
--     if (selector) then return selector, ">", string.gsub(comboSelector, "%s*%>%s*[^%s%+%~%>]-$", "") end

--     -- 后续兄弟选择器 div~p
--     selector = string.match(comboSelector, "%s*%~%s*([^%s%+%~%>]-)$");
--     if (selector) then return selector, "~", string.gsub(comboSelector, "%s*%~%s*[^%s%+%~%>]-$", "") end

--     -- 相邻兄弟选择器 div+p
--     selector = string.match(comboSelector, "%s*%+%s*([^%s%+%~%>]-)$");
--     if (selector) then return selector, "+", string.gsub(comboSelector, "%s*%+%s*[^%s%+%~%>]-$", "") end

--     return nil;
-- end

-- -- 是否是有效的元素选择器
-- local function IsValidElementSelector(selector, element, selectorType)
--     local elementSelector = element:GetStyle():GetSelector();
--     if (not selector) then return false end

--     if (selectorType == "nth-child") then
--         selector = tonumber(selector);
--         if (selector == element:GetIndexInParent()) then return true end 
--         return false;
--     elseif (selectorType == "[") then
--         local attrKey, attrVal = string.match(selector, "(%w+)=(%w+)");
--         local realAttrValue = element:GetAttrStringValue(attrKey);
--         if (realAttrValue ~= attrVal) then return false end
--         return true;
--     end

--     if (not elementSelector[selector]) then return false end
--     if ((string.match(selector, ":hover%s*$")) and not element:IsHover()) then return false end
--     return true;
-- end

-- -- 是否是祖先元素的选择器
-- local function IsAncestorElementSelector(element, selector)
--     local parentElement = element:GetParent();
--     if (not parentElement) then return false end
--     if (IsValidElementSelector(selector, parentElement)) then return true, parentElement end
--     return IsAncestorElementSelector(parentElement, selector);
-- end

-- -- 是否是元素的选择器
-- local function IsElementSelector(comboSelector, element)
--     local selector, selectorType, newComboSelector = GetTailSelector(comboSelector, element);
--     if (not IsValidElementSelector(selector, element, selectorType)) then return false end
--     local newSelector, newSelectorType = GetTailSelector(newComboSelector);
--     newSelector = commonlib.trim(newSelector or newComboSelector);
--     -- 后代选择器 div p
--     if (selectorType == " ") then
--         local isAncestorElementSelector, ancestorElement = IsAncestorElementSelector(element, newSelector);
--         if (not isAncestorElementSelector) then return false end
--         if (not newSelectorType) then return true end
--         return IsElementSelector(newComboSelector, ancestorElement);
--     end

--     -- 子选择器 div>p
--     if (selectorType == ">") then
--         local parentElement = element:GetParent();
--         if (not parentElement) then return false end
--         if (not IsValidElementSelector(newSelector, parentElement)) then return false end
--         if (not newSelectorType) then return true end
--         return IsElementSelector(newComboSelector, parentElement);
--     end

--     -- 后续兄弟选择器 div~p
--     if (selectorType == "~") then
--         local prevSiblingElement = element:GetPrevSiblingElement();
--         while (prevSiblingElement) do
--             if (IsValidElementSelector(newSelector, prevSiblingElement)) then break end
--             prevSiblingElement = prevSiblingElement:GetPrevSiblingElement();
--         end
--         if (not prevSiblingElement) then return false end
--         if (not newSelectorType) then return true end
--         return IsElementSelector(newComboSelector, prevSiblingElement);
--     end

--     -- 相邻兄弟选择器 div+p
--     if (selectorType == "+") then
--         -- StyleSheetDebug.If(element:GetAttrStringValue("id") == "debug", "--------------------------------------1");
--         local prevSiblingElement = element:GetPrevSiblingElement();
--         if (not prevSiblingElement) then return false end
--         -- StyleSheetDebug.If(element:GetAttrStringValue("id") == "debug", "--------------------------------------2", prevSiblingElementSelector, newSelector, newComboSelector, selector, comboSelector);
--         if (not IsValidElementSelector(newSelector, prevSiblingElement)) then return false end
--         -- StyleSheetDebug.If(element:GetAttrStringValue("id") == "debug", "--------------------------------------3");
--         if (not newSelectorType) then return true end
--         -- StyleSheetDebug.If(element:GetAttrStringValue("id") == "debug", "--------------------------------------4");
--         return IsElementSelector(newComboSelector, prevSiblingElement);
--     end

--     if (newSelector == "" or IsValidElementSelector(newSelector, element)) then return true end

--     return IsElementSelector(newSelector, element);
-- end

function StyleSheet:ctor()
    self.m_selector_style = {};
    self.m_animation_style = {};
end

function StyleSheet:Init(text)
    self:LoadString(text);
    return self;
end

-- 清空样式表
function StyleSheet:Clear()
    self.m_selector_style = {};
    self.m_animation_style = {};
end

-- 获取选择器样式
function StyleSheet:GetSelectorStyle(selector)
    self.m_selector_style[selector] = self.m_selector_style[selector] or Style:new():Init();
    return self.m_selector_style[selector];
end

-- 追加选择器样式 style_text 未解析
function StyleSheet:AppendSelectorStyle(selector, style_text)
    self:GetSelectorStyle(selector):AppendStyleText(style_text);
end

-- 追加样式表
function StyleSheet:AppendStyleSheet(stylesheet)
    for selector, style in pairs(stylesheet.m_selector_style) do
        commonlib.partialcopy(self:GetSelectorStyle(selector):GetStyleData(), style:GetStyleData());
    end
end

-- 从文件加载样式表
function StyleSheet:LoadFile(filename)
    self:LoadString(commonlib.GetFileText(filename) or "");
end


-- 加载字符串样式表
function StyleSheet:LoadString(stylesheet_text)
    -- local selector_style_text = self:LoadAnimationStyle(stylesheet_text);
    local selector_style_text = stylesheet_text;

    -- 解析选择器样式
    for selector_text, style_text in string.gmatch(selector_style_text, "([^{}]+){([^{}]+)}") do
        -- 提取样式
        local style = Style:new():Init(style_text);
        -- 逗号分隔 多个选择器共用样式
        for selector in string.gmatch(selector_text, "([^,]+),?") do
            -- 移除左右空白
            selector = string.match(selector, "^%s*(.-)%s*$");
            -- 追加选择器样式
            self:AppendSelectorStyle(selector, style);
        end
    end

    return self;
end

-- 生效选择器样式
function StyleSheet:ApplySelectorStyle(selector, style)
    style:AppendStyle(self:GetSelectorStyle(selector));
end

-- -- 生效组合选择器样式
-- function StyleSheet:ApplyComboSelectorStyle(element, style)
--     for selector in pairs(self.m_selector_style) do
--         if (IsElementSelector(selector, element)) then
--             self:ApplySelectorStyle(selector, style, element);
--         end
--     end
-- end

-- 应用选择器样式
function StyleSheet:ApplySelectorsStyle(selectors, style)
    for _, selector in ipairs(selectors) do
        self:ApplySelectorStyle(selector, style)
    end
end

-- 应用元素样式
function StyleSheet:ApplyElementStyle(element)
    local style = element:GetStyle();
    local selectors = element:GetStyleSelectors();
    self:ApplySelectorsStyle(selectors, style);
    -- 生效组合选择器样式
end

return StyleSheet;


-- -- 应用元素动画
-- function StyleSheet:ApplyElementAnimationStyle(element)
--     local style = element:GetStyle();
--     local animationName = style:GetAnimationName();
--     local function GetAnimation(sheet)
--         if (not sheet) then return nil end

--         local animation = sheet.m_animation_style[animationName];
--         if (animation) then return animation end

--         return GetAnimation(sheet.__inherit_stylesheet__);
--     end

--     element:GetAnimation():SetKeyFrames(GetAnimation(self));
-- end


-- 加载动画样式
-- function StyleSheet:LoadAnimationStyle(code)
--     self.m_animation_style = {};
--     return code;
--     -- 移除注释
--     -- code = string.gsub(code,"/%*.-%*/","");
--     -- local csscode, lastCssCodePos, codelen = "", 1, string.len(code);
--     -- -- 查找动画关键字
--     -- local startPos, endPos = string.find(code, "@keyframes", 1, true);
--     -- if (not startPos) then csscode = code end
--     -- while(startPos) do
--     --     local animationName = string.match(string.sub(code, endPos + 1), "([^{}]+)");
--     --     local index, count = string.find(code, "{", endPos + string.len(animationName), true), 1;
--     --     local sp, ep = nil, nil;
--     --     while (index and index < codelen) do
--     --         index = index + 1;
--     --         if (sp == nil) then sp = index end
--     --         local ch = string.sub(code, index, index);
--     --         if (ch == "{") then count = count + 1 end
--     --         if (ch == "}") then count = count - 1 end
--     --         if (count == 0) then
--     --             ep = index - 1
--     --             break;
--     --         end
--     --     end
--     --     local animationCss = string.sub(code, sp, ep);
--     --     animationName = string.match(animationName, "^%s*(.-)%s*$");
--     --     local animation = self.m_animation_style[animationName] or {};
--     --     self.m_animation_style[animationName] = animation;

--     --     -- print(animationName);
--     --     -- print(animationCss);

--     --     for selector_str, declaration_str in string.gmatch(animationCss, "([^{}]+){([^{}]+)}") do
--     --         local style = Parser.ParseString(declaration_str);
--     --         for selector in string.gmatch(selector_str, "([^,]+),?") do
--     --             selector = string.match(selector, "^%s*(.-)%s*$");
--     --             if (selector == "from") then selector = 0
--     --             elseif (selector == "to") then selector = 100
--     --             else
--     --                 selector = string.match(selector, "(%d+)");
--     --                 selector = selector and tonumber(selector) or 0;
--     --             end
--     --             style.percentage = selector;
--     --             table.insert(animation, style);
--     --         end
--     --     end
--     --     table.sort(animation, function(item1, item2) return item1.percentage < item2.percentage end);

--     --     csscode = csscode .. string.sub(lastCssCodePos, startPos - 1);
--     --     startPos, endPos = string.find(code, "@keyframes", index + 1, true);
--     --     if (not startPos) then
--     --         csscode = csscode .. string.sub(code, index + 1);
--     --     else
--     --         lastCssCodePos = index + 1;
--     --     end
--     -- end
-- end